﻿
/// <reference path="db.cache.js" />

$$.DB = new function () {
	var me = this;
	var memory = new $$.DBCache();
    var local = window.localStorage;
    Object.defineProperty(me, "VER", { value: 1180721 });
	Object.defineProperty(me, "NEVER", { value: -999 });

    //minute：分钟，默认60

    me.SetLocal = function (tb, key, row, minute) {
        if (memory.Set(tb, key, row, minute) === undefined) return;
        if (!local) return;
    	tb = (tb + "").trim().toLowerCase();
        key = tb + ":" + (key + "").trim().toLowerCase();

        if (!minute || !(minute > 0)) minute = 60;
        var now = new Date();
        now.setMinutes(now.getMinutes() + minute);

        row = $$.Jsonar.stringify(row, 10);
        local.setItem(key, now.getTime() + "\n" + row);
        return true;
    };
    me.Set = memory.Set;
    me.SetCache = memory.Set;

    me.SetLocals = function (tb, keys, rows, minute) {
        if (memory.Sets(tb, keys, rows, minute) === undefined) return;
        if (!local) return;
        if (!minute) minute = 0;
        tb = (tb + "").trim().toLowerCase();
        if (!minute || !(minute > 0)) minute = 60;
        var now = new Date();
        now.setMinutes(now.getMinutes() + minute);
        var len = Math.min(keys.length, rows.length);
        for (var i = 0; i < len; i++) {
            var key = ("" + keys[i]).trim().toLowerCase();
            if (!key) continue;
            var row = rows[i];
            if (!row && row !== 0 && row !== false) continue;

            key = tb + ":" + key;
            row = $$.Jsonar.stringify(row, 10);
            local.setItem(key, now.getTime() + "\n" + row);
        }
        return true;
    };
    me.Sets = memory.Sets;
    me.SetCaches = memory.Sets;

    me.GetLocal = function (tb, key, callback) {
		if (!callback) { console.error("db Get/GetLocal no callback:" + tb); return; }
		var row = memory.Get(tb, key);
		if (row === undefined) { callback(); return; }
		if (row || row === 0 || row === false) { callback(row); return; }
		if (!local) { callback(); return; }

    	tb = (tb + "").trim().toLowerCase();
		var k = tb + ":" + (key + "").trim().toLowerCase();
		row = local.getItem(k); if (!row) { callback(); return; }
		var idx = row.indexOf("\n"); if (idx < 0) { local.removeItem(k); callback(); return; }
		var ticks = row.substr(0, idx);
		if (!(ticks = $$.ParseInt(ticks))) { local.removeItem(k); callback(); return; }
		var now = new Date();
		if (now.getTime() > ticks) { local.removeItem(k); callback(); return; }
		row = $$.Jsonar.parse(row.substr(idx + 1));
		memory.Set(tb, key, row, 15);
		callback(row);
    };
    me.Get = me.GetLocal;
    me.GetCache = memory.Get;

    me.GetLocals = function (tb, keys, callback) {
		if (!callback) { console.error("db Gets/GetLocals no callback:" + tb); return; }
		var rows = memory.Gets(tb, keys);
		if (rows === undefined) { callback(undefined); return; }
		if (rows && rows.uns && rows.uns.length < 1) { callback(rows); return; }
		if (!local) { callback(null); return; }

		tb = ("" + tb).trim().toLowerCase();
		if (!rows) rows = [];
		var uns = rows.uns;
		rows.uns = [];
		if (uns) {
			for (var i = 0, len = uns.length; i < len; i++) {
				getRow((keys[uns[i]] + "").trim().toLowerCase(), uns[i]);
			}
		}
		else {
			for (var i = 0, len = keys.length; i < len; i++) {
				getRow(keys[i], i);
			}
		}
		callback(rows);

		function getRow(id, pos) {
			if (!id || !(pos >= 0)) return;
			var key = tb + ":" + id;
			var row = local.getItem(key);
			if (!row) { rows.uns.push(pos); return; }

			var idx = row.indexOf("\n");
			if (idx < 0) { local.removeItem(key); rows.uns.push(pos); return; }
			var ticks = row.substr(0, idx);
			if (!(ticks = $$.ParseInt(ticks))) { local.removeItem(key); rows.uns.push(pos); return; }
			var now = new Date();
			if (now.getTime() > ticks) { local.removeItem(key); rows.uns.push(pos); return; }
			row = $$.Jsonar.parse(row.substr(idx + 1));
			if (row || row === 0 || row === false) {
				memory.Set(tb, id, row, 15);
				rows[pos] = row;
			}
		}
    };
    me.Gets = me.GetLocals;
    me.GetCaches = memory.Gets;

    me.Remove = function (tb, key) {
    	if (memory.Remove(tb, key) === undefined) return;
    	if (!local) return;
    	tb = (tb + "").trim().toLowerCase();
    	key = tb + ":" + (key + "").trim().toLowerCase();
    	local.removeItem(key);
        return true;
    };
    me.Removes = function (tb, keys) {
    	if (memory.Removes(tb, keys) === undefined) return;
    	if (!local) return;
    	tb = ("" + tb).trim().toLowerCase();
    	for (var i = 0; i < keys.length; i++) {
    		var key = tb + ":" + ("" + keys[i]).trim().toLowerCase();
    		local.removeItem(key);
    	}
        return true;
    };

    me.Clear = function (tb, iscache) {
    	//tb=** 清除所有表
    	if (memory.Clear(tb) === undefined) return;
    	if (iscache === true || !local) return;
    	if (tb === "**") { local.clear(); local.setItem("DB!Ver", Ver); return; }
    	var idx = local.length;
    	if (idx < 1) return;
    	tb = (tb + "").trim().toLowerCase();
    	while (--idx >= 0) {
    		var key = local.key(idx);
    		if (key.startsWith(tb, 0)) local.removeItem(key);
    	}
    	local.setItem("DB!Ver", Ver);
        return true;
    }


    function init() {
        if (!local) return;
        var ver = local.getItem("DB!Ver") || "";
        ver = Number(ver);
        if (ver && ver === me.VER) return;
        if (!ver) { local.setItem("DB!Ver", me.VER); return; }
        local.setItem("DB!Ver", me.VER);
        var vis = local.getItem("app:vis");
        local.clear();
        local.setItem("DB!Ver", me.VER);
        if (vis) local.setItem("app:vis", vis);
    }
    init();
};